<?php
declare (strict_types = 1);
namespace Haozing\FastCore\Abstract;

use Exception;
use Haozing\FastCore\Interfaces\BaseServiceInterface;
use Haozing\FastCore\Model\Model;
use Haozing\FastCore\Traits\ServiceTrait;
use Hyperf\Collection\Collection;
use Hyperf\Database\Model\Builder;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Logger\LoggerFactory;

/**
 * Class AbstractMapper
 * @package Mine\Abstracts
 */
abstract class AbstractService implements BaseServiceInterface
{
    use ServiceTrait;
    #[Inject]
    protected LoggerFactory $logger;

    public Model $model;

    abstract public function getModel(): Model;

    public function __construct()
    {
        $this->model = $this->getModel();
    }

    /**
     * 查询分类表单条数据 - 根据ID
     * @param int $id ID
     * @param string[] $field 查询字段
     */
    public function getOneById(int $id, array $field = ['*'])
    {
        return $this->model->find($id, $field);
    }

    /**
     * 查询分类表单条数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @return Builder|\Hyperf\Database\Model\Model|\Hyperf\Database\Query\Builder|object|null
     */
    public function getOneByWhere(array $where, array $field = ['*'], array $options = [])
    {
        return $this->model->getOneByWhere($where, $field,$options);
    }
    /**
     * 查询分类表单条数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @return Builder|\Hyperf\Database\Model\Model|\Hyperf\Database\Query\Builder|object|null
     */
    public function getOneByWhereTenant(array $where, array $field = ['*'], array $options = [])
    {
        return $this->model->getOneByWhereTenant($where, $field,$options);
    }
    /**
     * 查询分类表多条数据 - 根据ID
     * @param array $ids ID
     * @param string[] $field 查询字段
     */
    public function getManyByIds(array $ids, array $field = ['*'])
    {
        return $this->model->whereIn('id',$ids)->get($field);
    }

    /**
     * 查询分类表多条数据pluck - 根据ID
     * @param array $ids ID
     * @param string $field 查询字段
     */
    public function getManyPluckByIds(array $ids, string $field = 'id'): array
    {
        return $this->model->whereIn('id',$ids)->pluck($field)->toArray();
    }
    /**
     * 查询分类表多条数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @param int $limit
     * @return Collection|Builder[]|\Hyperf\Database\Model\Collection
     */
    public function getManyByWhere(array $where, array $field = ['*'], array $options = [], int $limit = 1000)
    {
        return $this->model->getListByWhere($where, $field,$options, $limit);
    }
    /**
     * 查询分类表多条数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @param int $limit
     * @return Collection|Builder[]|\Hyperf\Database\Model\Collection
     */
    public function getManyByWhereTenant(array $where, array $field = ['*'], array $options = [], int $limit = 1000)
    {
        return $this->model->getListByWhereTenant($where, $field,$options, $limit);
    }
    /**
     * 查询分类表多条数据Pluck - 根据条件
     * @param array $where 条件
     * @param string $field 查询字段
     * @return array
     */
    public function getManyPluckByWhere(array $where, string $field = 'id'): array
    {
        return $this->model->optionWhere($where)->pluck($field)->toArray();
    }

    /**
     * 查询分类表多条数据Pluck - 根据条件
     * @param array $where 条件
     * @param string $field 查询字段
     * @return array
     */
    public function getManyPluckByWhereTenant(array $where, string $field = 'id'): array
    {
        return $this->model->pluckByTenant($where, $field)->toArray();
    }
    /**
     * 查询分类表分页数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @return mixed
     */
    public function getPage(array $where, array $field = ['*'],array $options = [])
    {
        return $this->model->getPageByWhere($where, $field, $options);
    }
    /**
     * 查询分类表分页数据 - 根据条件
     * @param array $where 条件
     * @param string[] $field 查询字段
     * @param array $options
     * @return mixed
     */
    public function getPageTenant(array $where, array $field = ['*'],array $options = [])
    {
        return $this->model->getPageByWhereTenant($where, $field, $options);
    }
    /**
     * 添加分类表单条数据
     * @param array $data 添加数据
     * @return int 自增ID
     */
    public function addOne(array $data): int
    {
        return $this->model->addOne($data);
    }
    /**
     * 添加分类表单条数据
     * @param array $data 添加数据
     * @return int 自增ID
     */
    public function addOneTenant(array $data): int
    {
        return $this->model->addOneTenant($data);
    }
    /**
     * 添加分类表多条数据
     * @param array $data 添加数据
     * @return bool 操作结果
     */
    public function addMany(array $data): bool
    {
        return $this->model->addAll($data);
    }
    /**
     * 添加分类表多条数据
     * @param array $data 添加数据
     * @return bool 操作结果
     */
    public function addManyTenant(array $data): bool
    {
        return $this->model->addAllTenant($data);
    }
    /**
     * 修改分类表单条数据 - 根据ID
     * @param int $id ID
     * @param array $data 修改数据
     * @return int 修改条数
     */
    public function updateById(int $id, array $data): int
    {
        return $this->model->updateOneById($id, $data);
    }

    /**
     * 修改分类表单条数据 - 根据条件
     * @param array $where 条件
     * @param array $data 修改数据
     * @param array $options 修改选项
     * @return int 修改条数
     * @throws Exception
     */
    public function updateByWhere(array $where, array $data,array $options=[]): int
    {
        return $this->model->updateByWhere($where, $data,$options);
    }
    /**
     * 修改分类表单条数据 - 根据条件
     * @param array $where 条件
     * @param array $data 修改数据
     * @param array $options 修改选项
     * @return int 修改条数
     * @throws Exception
     */
    public function updateByWhereTenant(array $where, array $data,array $options=[]): int
    {
        return $this->model->updateByWhereTenant($where, $data,$options);
    }
    /**
     * 删除分类表单条数据 - 根据ID
     * @param int $id ID
     * @return int 删除条数
     */
    public function deleteById(int $id): int
    {
        return $this->model->destroy($id);
    }

    /**
     * 删除分类表多条数据 - 根据ID
     * @param array $ids ID
     * @return int 删除条数
     */
    public function deleteManyByIds(array $ids): int
    {
        return $this->model->destroy($ids);
    }

    /**
     * 删除分类表数据 - 根据条件
     * @param array $where 条件
     * @return int 删除条数
     */
    public function deleteByWhere(array $where,array $options =[]): int
    {
        return $this->model->deleteByWhere($where,$options);
    }
    /**
     * 删除分类表数据 - 根据条件
     * @param array $where 条件
     * @return int 删除条数
     */
    public function deleteByWhereTenant(array $where,array $options =[]): int
    {
        return $this->model->deleteByWhereTenant($where,$options);
    }
    /**
     * 批量修改 - 根据ID
     * @param array $data 修改数据 `[['id'=>1, 'name' => 'name1'], ['id' => 2, 'name' => 'name2']]`
     * @return int 修改条数
     */
    public function updateMany(array $data): int
    {
        return $this->model->batchUpdateByIds($data);
    }

    /**
     * 保存关联数据
     * @param string $whereColumn 条件字段
     * @param int $whereId 条件字段的值
     * @param string $DataColumn 保存字段
     * @param array $DataValue   保存的值
     * @return mixed
     */
    public function saveRelationshipById(string $whereColumn,int $whereId,string $DataColumn, array $DataValue): mixed
    {
        //先删除，在插入
        $this->model->where($whereColumn,$whereId)->whereIn($DataColumn,$DataValue)->delete();
        //插入关联数据
        $data = [];
        for($i=0;$i<count($DataValue);$i++){
            $data[] = [
                $whereColumn => $whereId,
                $DataColumn => $DataValue[$i],
            ];
        }
        return $this->model->addOne($data);
    }

    /**
     * 获取list转为map
     * @param array $where 条件
     * @param string $field 查询字段
     * @param string[] $fields 返回的字段
     * @return array
     */
    public function getMap(array $where, string $field, array $fields = ['*']): array
    {
        $map = [];
        $list = $this->getManyByWhere($where, $fields, [], 10000);

        // 如果不是空，那么要转为数组
        if (!empty($list)) {
            $list = $list->toArray();
            foreach ($list as $item) {
                $map[$item[$field]] = $item;
            }
        }

        return $map;
    }
    /**
     * 获取list转为map
     * @param array $where 条件
     * @param string $field 查询字段
     * @param string[] $fields 返回的字段
     * @return array
     */
    public function getMapTenant(array $where, string $field, array $fields = ['*']): array
    {
        $map = [];
        $list = $this->getManyByWhereTenant($where, $fields, [], 10000);

        // 如果不是空，那么要转为数组
        if (!empty($list)) {
            $list = $list->toArray();
            foreach ($list as $item) {
                $map[$item[$field]] = $item;
            }
        }

        return $map;
    }
    /**
     * 根据条件获取某个字段的数量
     */
    public function getCountByWhere(array $where, string $field = 'id', array $options = []): int
    {
        return $this->model->optionWhere($where, $options)
            ->count($field);
    }
    /**
     * 根据条件获取某个字段的数量,自动注入租户id
     */
    public function getCountByWhereTenant(array $where, string $field = 'id', array $options = []): int
    {
        return $this->model->countByTenant($where,$field, $options);
    }
}
